using System;
using System.Xml;
//using CStock;
using System.ComponentModel;
using CUtil;
using System.Reflection;

using System.IO; 
using System.Xml.Serialization;


namespace CUtil
{
	/// <summary>
	/// Summary description for XMLSerializable.
	/// </summary>
	public class XMLSerializable : IXMLSerializable
	{
		
		//protected string name;	
		protected string fileName;
        protected event ObjectChangedEvent objectChanged;
		protected string path;
		protected string iD;
        string oldID ;

        
		public XMLSerializable()
		{
			
		}

		#region serialize

        [Browsable(false)]
        [Category("Base\\string"), DescriptionAttribute("string")]
		public virtual string ID
		{
			get 
			{ 
				return this.iD; 
			}
			set 
			{ 
				this.iD = value ; 
			}
		}
        public virtual void RaiseObjectChangedEvent(object sender, string propName, object oldVal, object newVal)
        {
            if (this.objectChanged != null)
            {
                this.objectChanged(this, new ObjectChangedEventArgs(sender, propName, oldVal, newVal));
            }

        }
        [Browsable(false)]
		//[System.Xml.Serialization.XmlIgnoreAttribute()]
		public virtual string Name
		{
			get 
			{ 
				//return this.name;
                return this.iD; 

			}
			set 
			{
                oldID = this.iD;

				//this.name = value ;
                this.iD = value;
                //this.RaiseObjectChangedEvent(this, "ID", oldID, iD);

                //this.Serialize();


			}
		}
       

		/// <summary>
		/// The File name is always taken after the name 
		/// </summary>
		[Browsable(false)]
		[System.Xml.Serialization.XmlIgnore()]
		public virtual string FileName
		{
			get
			{
				return this.iD + ".xml";
			}

		}

		[Browsable(false)]
		[System.Xml.Serialization.XmlIgnore()]
		public virtual string Path
		{
			get
			{
				
				return this.path;
			}
			
		}
        //have to implement this in every class!!
        public virtual bool ResetPathFromConfiguration()
        {
            
            return false;
        }
        
        public bool Exists()
        {
            string strFile = path + this.iD + ".xml";

            return System.IO.File.Exists(strFile);

            
        }

		/// <summary>
		/// serializes the class with the convention
		/// -into the directory speciefied by this.path
		/// -into the file specified by this.name 
		/// -with the file name extension .xml
		/// </summary>
		/// <returns></returns>
		public virtual bool Serialize()
		{
			System.Diagnostics.Debug.Assert( ! String.IsNullOrEmpty(this.path),"Serializer error: Path for: " + this.iD);
            System.Diagnostics.Debug.Assert(! String.IsNullOrEmpty(this.iD), "Serializer error: Path for: " + this.iD);

			if(this.path != null && this.path != string.Empty && this.iD != null && this.iD != string.Empty)
			{
				//creates directory if it does not exist
				CUtil.DirectoryUtil.CreateDirectory(this.path);

//				System.Diagnostics.Debug.Assert(this.iD != null,"iD not set when trying to serialize");
//				if( this.iD == null || this.iD == string.Empty)
//					return false;
				try
				{
				
					return XMLSerializable.SerializeObject(this , this.path + "\\"  + this.iD + ".xml");
				}
				catch(Exception e)
				{
					System.Diagnostics.Debug.Assert(false,"Error serializing " + "; error message is " + e.Message);
					return false;
				}	
			}
			else
			{
				return false;
			}
		}
		
	
		/// <summary>
		/// 
		/// de - serializes the class with the convention
		/// -into the directory speciefied by this.path
		/// -into the file specified by this.name 
		/// -with the file iD extension .xml
		/// 
		/// <returns></returns>
		/// </summary>
		/// <returns></returns>
		public virtual object DeSerialize()
		{
			System.Diagnostics.Debug.Assert( (this.path != null && this.path != string.Empty),"Path not set when trying to De-Serialize");
			System.Diagnostics.Debug.Assert((this.iD != null  && this.iD != string.Empty) ,"iD not set when trying to De-Serialize");

			if(this.path != string.Empty && this.iD != string.Empty)
			{

				//creates directory if it does not exist
				CUtil.DirectoryUtil.CreateDirectory(this.path);

				
				

				object iser = (object) this;
				System.Diagnostics.Debug.Assert(iser != null,"Could not create instance for : " + this.iD);
				
				if(XMLSerializable.DeSerializeObject( ref iser,this.path + "\\"  + this.iD + ".xml"))
					return iser;
				else
					return null;
					
				
			}
			else
			{
				return null;
			}
		}
	
	
        /// 
        /// <returns></returns>
        /// </summary>
        /// <returns></returns>
        public virtual bool DeSerialize(ref object iser)
        {

            return DeSerializeStatic(ref iser, this.path, this.iD);


        }

        private static bool CheckParameters(object iser, string myPath, string myID)
        {
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(myPath), "Serializer error: Path for: " + myID);
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(myID), "Serializer error: Path for: " + myID);


           System.Diagnostics.Debug.Assert(iser != null, "ReferenceObect = null " + myID);

            System.Diagnostics.Debug.Assert(iser != null, "SW error : in the serializer, the initial object has to be set ");
            

            if (myPath!= string.Empty && myID  != string.Empty)
            {
                return true;
            }
            return false;

        }

        public static bool DeSerializeStatic(ref object iser, string myPath, string myID)
        {
            if (!CheckParameters(iser, myPath, myID))
                return false;


            //creates directory if it does not exist
            CUtil.DirectoryUtil.CreateDirectory(myPath);

           string fileNameSearched = myPath + "\\" + myID + ".xml";
            if (System.IO.File.Exists(fileNameSearched))
            {
                return XMLSerializable.DeSerializeObject(ref iser, fileNameSearched);
            }
            else
            {
                return false;
            }
           
        }

        public static void DeSerializeObject(ref object o, System.IO.Stream fileStream)
		{
			TextReader reader = null;
			try
			{
				XmlSerializer serializer = new XmlSerializer(o.GetType());
				reader = new StreamReader(fileStream);
				o = serializer.Deserialize(reader);
				
			}
			catch(Exception e)
			{
				System.Diagnostics.Debug.Assert(false,"XML Serialization: could not de - serialize object " + o.ToString() + "; error message is : " + e.Message);
			}
			//			finally
			//			{
			if(reader != null)
				reader.Close();
			//			}
		}
        public static bool SerializeObject(object o, System.IO.Stream fileStream)
        {
            TextWriter writer = null;
            writer = new StreamWriter(fileStream);

            return XMLSerializable.SerializeBase(o, writer);
        }
        public static bool SerializeBase(object o, TextWriter writer)
        {
            bool bret;
            try
            {
                Type t = o.GetType();
                XmlSerializer serializer = new XmlSerializer(t);
                //eventually create directory 


                serializer.Serialize(writer, o);
                writer.Close();
                bret = true;
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.Assert(false, "XML Serialization: could not serialize object " + o.ToString() + "; error message is : " + e.Message);
                writer.Close();
                bret = false;
            }
           
            return bret;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="o"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool SerializeObject(object o, string filename)
        {
            
            TextWriter writer = null;
            writer = new StreamWriter(filename);

            bool b = XMLSerializable.SerializeBase(o, writer);
            if (!b)
                System.IO.File.Delete(filename);

            return b;



        }

		public static bool DeSerializeObject(ref object o,string filename)
		{

			bool breturn;
			TextReader reader = null;
			try
			{
				//search for file:
				if( !System.IO.File.Exists(filename) )
				{
					//file does not exist
					//System.Diagnostics.Debug.Assert(false,"XML Serialization: Some file is missing : " + filename );
					return false;
				}

                Type t = o.GetType();
				XmlSerializer serializer = new XmlSerializer(t);
				reader = new StreamReader(filename);
				o = serializer.Deserialize(reader);
				breturn = true;
				
			}
			catch(Exception e)
			{
				System.Diagnostics.Debug.Assert(false,"Could not get from disk: " + o.ToString() + " - file - " + filename + " ; error message is : " + e.Message);
				breturn = false;
			}
			finally
			{
				if(reader != null)
					reader.Close();
			}
			return breturn;
		}
	
		#endregion

        #region remove all
        
        public bool RemoveAllInstances()
        {
            return XMLSerializable.RemoveAllXML(this.path);

        }
        public static bool RemoveAllXML(string myPath)
        {
            
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(myPath), "Path not set when trying to De-Serialize");
          
            if (myPath != string.Empty)
            {

                //creates directory if it does not exist
                CUtil.DirectoryUtil.CreateDirectory(myPath);

                DirectoryInfo di = new DirectoryInfo(myPath);
                FileInfo[] fia = di.GetFiles("*.xml");

               
                for (int i = 0; i < fia.Length; i++)
                {
                    FileInfo fi = fia[i];
                    fi.Delete();

                }
                return true;
              
            }
            else
            {
                return false;
            }
        }
        public static bool RemoveAllData(string myPath)
        {
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(myPath), "Path not set when trying to De-Serialize");
          
            
            if (myPath != string.Empty)
            {

                //creates directory if it does not exist
                CUtil.DirectoryUtil.CreateDirectory(myPath);

                DirectoryInfo di = new DirectoryInfo(myPath);
                //1. remove all files
                FileInfo[] fia = di.GetFiles();


                for (int i = 0; i < fia.Length; i++)
                {
                    FileInfo fi = fia[i];
                    fi.Delete();

                }
                //2. remove all directories

                DirectoryInfo[] dia = di.GetDirectories();


                for (int i = 0; i < dia.Length; i++)
                {
                    DirectoryInfo fi = dia[i];
                    fi.Delete(true);

                }
                //2. remove all directories

                return true;

            }
            else
            {
                return false;
            }
        }
        public event ObjectChangedEvent ObjectChanged
        {
            add
            {
                this.objectChanged += value;
            }


            remove
            {
                if (objectChanged != null)
                {
                    objectChanged -= value;
                }
            }
        }
       

        #endregion

   

    }

   
}
